/*
Copyright 2008, 2009 Joonas Lehtolahti

This file is part of Openfire-C.

Openfire-C is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Openfire-C is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with Openfire-C.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef _XFIREPACKETANALYZE_H_
#define _XFIREPACKETANALYZE_H_

#define XFPREF_ENABLE_SOUNDS 0x04
#define XFPREF_ENABLE_ENGROSSED_SOUNDS 0x05
#define XFPREF_ENABLE_TIMESTAMPS 0x06
#define XFPREF_ENABLE_JOIN_LEAVE_SOUNDS 0x07
#define XFPREF_ENABLE_JOIN_LEAVE_GROUPCHAT_SOUNDS 0x08
#define XFPREF_ENABLE_VOICECHAT_CALL_SOUNDS 0x09
#define XFPREF_TOOLTIP_LOGON 0x10
#define XFPREF_TOOLTIP_DOWNLOADS 0x11
#define XFPREF_ENABLE_SCREENSHOT_SOUNDS 0x12
#define XFPREF_SHOW_FOF 0x13
#define XFPREF_SHOW_OFFLINE_FRIENDS 0x14

#define XFVALUE_GC_JOIN_SUCCESS 0x00
#define XFVALUE_GC_JOIN_NEED_PASSWORD 0x04
#define XFVALUE_GC_JOIN_WRONG_PASSWORD 0x05

#define XFVALUE_GC_TYPE_NORMAL 0x01
#define XFVALUE_GC_TYPE_LIVE 0x03

#define XFP_IS_PREF(prefset, offset) (  (prefset)&( 1 << (offset) )  )
#define XFP_SET_PREF(prefset, offset) prefset |= ( 1 << (offset) )
#define XFP_DEL_PREF(prefset, offset) prefset &= ~( 1 << (offset) )

#define XFNH_CONTINUE 0
#define XFNH_NOHANDLE 0x1
#define XFNH_NOITERATION 0x2
#define XFNH_FATAL 0x4
#define XFNH_USER_MASK 0xffff0000

#define XFIH_FATAL -5				/* fatal error, try to quit as fast as possible */
#define XFIH_PARSING_FAILED -4		/* parsing network packet failed */
#define XFIH_OTHER_ERROR -3			/* reserved for future use */
#define XFIH_NULL_INST -2			/* NULL XFINST was passed */
#define XFIH_SOCKET_ERROR -1		/* socket reported error, OS specific error functions might have more data */
#define XFIH_SOCKET_CLOSED 0		/* connection was closed on the socket */
#define XFIH_PENDING 0x1	/* data or handlers pending */
#define XFIH_HANDLED 0x2	/* packet was handled */
#define XFIH_UNKNOWN 0x4	/* packet was unknown */
#define XFIH_EXTERNAL 0x8	/* external handlers were called */
#define XFIH_NONFATAL 0x10	/* a non-fatal error was encountered */
#define XFIH_BLOCKED 0x20	/* external handler wanted to prevent internal handler where impossible */
#define XFIH_MORE 0x40		/* external handler wanted to prevent internal handler where impossible */

#define XFSEL_OK 1
#define XFSEL_READ 2
#define XFSEL_WRITE 4

/* Handler function -only structures */

struct XfVersionUpdate {
	unsigned int version;
	non0string  *fileurl;
	unsigned int command;
	unsigned int fileid;
};

struct XfFriendInvite {
	non0string   *username;
	non0string   *nickname;
	non0string   *invite_text;
};

struct XfFriendSearchResult {
	non0string   *name;
	non0string   *lname;
	non0string   *fname;
};

struct XfClanInvite {
	unsigned int  clanid;
	non0string   *shortname;
	non0string   *longname;
	unsigned int  clantype;
	non0string   *username;
	non0string   *nickname;
	non0string   *invite_text;
};

/* XfirePacketAnalyze structures */

struct XfFriendsGroup {
	unsigned int  groupid;
	non0string   *name;
	LinkedList   *users; /* Pointers to XfFriend structures */
};

struct XfGameServerList {
	unsigned int gameid;
	LinkedList  *servers; /* struct XfGameData */
};

struct XfGameDataExt {
	LinkedList *names;
	LinkedList *values;
	/* The rest only used for friends' favorites */
	LinkedList *byfriends; /* Pointers to XfFriend structures */
};

struct XfGameData {
	unsigned int          gameid;
	unsigned int          ip;
	unsigned int          port;
	unsigned int          gameid_old;
	unsigned int          ip_old;
	unsigned int          port_old;
	struct XfGameDataExt *extdata;
};

struct XfFavoriteServers {
	unsigned int  maxfavorites;
	LinkedList   *servers;
};

struct XfScreenshotInfo {
	unsigned int       index;
	struct XfGameData *game;
	non0string        *description;
	unsigned int       timestamp;
	non0string        *guid;
	unsigned int       locked;
	unsigned int       filesize;
};

struct XfVideoInfo {
	unsigned int       index;
	non0string        *title;
	non0string        *description;
	unsigned int       filesize;
	unsigned int       res_x;
	unsigned int       res_y;
	unsigned int       frames;
	unsigned int       fps;
	unsigned int       gameid;
	unsigned int       timestamp;
};

struct XfClanMember {
	struct XfFriend *user; /* The actual user structure */
	struct XfClan *clan;   /* Link to the clan */
	non0string *nickname;  /* Nickname in this clan */
};

struct XfClanNews {
	unsigned int newsid;
	struct XfClan *clan;   /* Link to the clan */
	non0string  *title;
	unsigned int timestamp;
	non0string  *username;
	non0string  *nickname;
	non0string  *extra;
};

struct XfClanEvent {
	unsigned int eventid;
	struct XfClan *clan;   /* Link to the clan */
	unsigned int gameid;
	non0string  *title;
	unsigned int starttime;
	unsigned int endtime;
};

struct XfClan {
	unsigned int clanid;
	non0string  *shortname; /* Clan shortname (url name) */
	non0string  *longname;  /* Clan long name */
	BTree       *members;   /* BTree of XfClanMember structs */
	LinkedList  *news;		/* LinkedList of XfClanNews structs */
	LinkedList  *events;	/* LinkedList of XfClanEvent structs */
	unsigned int clantype;
};

struct XfFriendP2P {
	unsigned int ip;
	unsigned int port;
	unsigned int localip;
	unsigned int localport;
	unsigned int status;
	non0string  *salt;
};

struct XfBroadcast {
	non0string  *title;
	non0string  *description;
	non0string  *sessionid;
	non0string  *sessionimage;
	non0string  *ipaddress;
	non0string  *watchers;
	non0string  *ipport;
	unsigned int friends_only;
};

struct XfFriendExt {
	LinkedList         *screenshots;
	LinkedList         *videos;
	LinkedList         *clans;
	unsigned int        avatartype;
	unsigned int        avatarnumber;
	struct XfFriendP2P *p2p;
	struct XfBroadcast *live_video;
};

struct XfFriend {
	unsigned int        userid;
	non0string         *sid;
	non0string         *username;
	non0string         *nickname;
	non0string         *status;
	struct XfGameData  *game;
	struct XfGameData  *voice;
	struct XfFriendExt *extdata;
	void               *freedata; /* for host program to use */
};

struct XfChatRoomUser {
	struct XfFriend *user;
	unsigned int     permission;
	unsigned int     using_voice;
	void            *freedata; /* for host program to use */
};

struct XfVoiceHostUser {
	unsigned int ip;
	unsigned int port;
	unsigned int localip;
	unsigned int localport;
	unsigned int status;
	non0string  *salt;
};

struct XfChatRoomVoice {
	non0string   *session_id;
	struct XfVoiceHostUser  *host_info;
	unsigned int  host_type;
	unsigned int  voice_enabled;
	unsigned int  host_userid;
	unsigned int  max_participants;
	unsigned int  voice_quality;
	unsigned int  voice_ip;
	unsigned int  voice_port;
};

struct XfChatRoom {
	non0string  *gcid;
	non0string  *name;
	non0string  *motd;
	BTree       *users;
	unsigned int info_timestamp;
	unsigned int info_usercount;
	unsigned int set_saved;
	unsigned int set_silenced;
	unsigned int set_showjoinpart;
	unsigned int set_defaultperm;
	unsigned int set_protected;
	unsigned int set_access;
	unsigned int set_allowvoice;
	unsigned int set_type;
	struct XfChatRoomVoice *voice;
	struct XfChatRoomUser *self;
	void        *freedata;
};

struct XfNetworkHandlerList {
	unsigned int pid;
	LinkedList  *funcs;
};

struct XfNetworkInstance {
	int          sock;             /* Connection socket */
	BTree       *network_handlers; /* Registered network packet handlers */
	non0string  *incoming;         /* Incoming buffer */
	size_t       in_completed;     /* Completed bytes in incoming buffer */
	non0string  *outgoing;         /* Outgoing buffer */
	size_t       out_completed;    /* Completed bytes in outgoing buffer */
	LinkedList  *send_queue;       /* Packet queue */
	fd_set      *readset;          /* File descriptors for reading */
	fd_set      *writeset;         /* File descriptros for writing */
	fd_set      *xfireset;         /* All file descriptors used by Openfire-C */
	int          fdmax;            /* The largest file descriptor in readset/writeset/xfireset */
	void        *unused;
};

typedef struct StructXfireInstance {
	struct XfNetworkInstance *network;
	struct XfFriend          *self;         /* Includes userid, sid, nick, status, clans, screenshots of self */
	BTree                    *friends;      /* BTree of XfFriend structs (friends) */
	BTree                    *other_people; /* BTree of XfFriend structs (other known people such as clanmates and fof) */
	BTree                    *groups;       /* BTree of XfFriendsGroup structs */
	struct XfFavoriteServers *fav_servers;  /* Favorite servers */
	BTree                    *chatrooms;    /* BTree of XfChatRoom structs */
	unsigned int              prefs;        /* Xfire client preferences */
	BTree                    *known_clans;  /* BTree of all clans of you and your friends for lookup */
	BTree                    *online_people;/* BTree of all online people for faster lookup */
	BTree                    *friends_favs; /* BTree of XfGameServerList structs */
	BTree                    *game_servers; /* BTree of XfGameServerList structs */
	unsigned int              imindex;      /* auto-incremented index for sent messages */
	unsigned int              debug;        /* Set library debug message level, 0 = no messages */
	/* TODO: File transfer stuff like channels */
	void *placeholder3;
	/* Replace above with some meaningful structs... now they are just to fill the struct to multiple of 4 */
	void                     *freedata;     /* Reserved for host program */
} *XFINST;

struct XfNetworkHandler {
	void *func;
	void *freedata;
};

/* Functions */
DLLEXPORT(unsigned int) XfireDefaultPreferences(unsigned int initials);

DLLEXPORT(XFINST) XfireInstance(int socketid);
DLLEXPORT(struct XfNetworkHandler*) XfireInst_RegisterHandler(
	XFINST inst, unsigned int pid, void *func, void *freedata);
DLLEXPORT(unsigned int) XfireInst_UnregisterHandler(
	XFINST inst, unsigned int pid, void *func, void *freedata);
DLLEXPORT(unsigned int) XfireInst_SendPacket(XFINST inst,
	struct XfirePacket *packet);
DLLEXPORT(int) XfireInst_SendMessage(XFINST inst,
	struct XfFriend *xff, non0string *msg);
DLLEXPORT(int) XfireInst_SendMessageC(XFINST inst,
	struct XfFriend *xff, non0string *msg);
DLLEXPORT(int) XfireInst_UserLogin(XFINST inst,
	non0string *username, non0string *password, non0string *salt,
	unsigned int flags);
DLLEXPORT(int) XfireInst_UserLoginSaved(XFINST inst,
	non0string *username, non0string *pwhash, non0string *salt,
	unsigned int flags);
DLLEXPORT(int) XfireInst_ProcessSend(XFINST inst);
DLLEXPORT(int) XfireInst_ProcessRecv(XFINST inst);
DLLEXPORT(int) XfireInst_ProcessRecvPacket(XFINST inst, non0string *data, struct XfirePacket *packet);
DLLEXPORT(int) XfireSeqConnect(XFINST inst, struct sockaddr_in *address);
DLLEXPORT(int) XfireInst_DefaultConnect(XFINST inst, char *hostname);
DLLEXPORT(int) XfireInst_CheckNetwork(XFINST inst, struct timeval *timeout,
	fd_set *readset, fd_set *writeset);
DLLEXPORT(int) XfireInst_FD_SET_read(XFINST inst, int fd);
DLLEXPORT(int) XfireInst_FD_SET_write(XFINST inst, int fd);
DLLEXPORT(int) XfireInst_FD_CLR_read(XFINST inst, int fd);
DLLEXPORT(int) XfireInst_FD_CLR_write(XFINST inst, int fd);

DLLEXPORT(struct XfClan*) XfireInst_AddNewClan(XFINST inst, unsigned int clanid);
DLLEXPORT(struct XfClan*) XfireInst_FindClanByClanid(XFINST inst, unsigned int clanid);
DLLEXPORT(struct XfFriendsGroup*) XfireInst_FindGroupByGroupid(XFINST inst, unsigned int groupid);
DLLEXPORT(struct XfFriend*) XfireInst_FindUserByUserid(XFINST inst, unsigned int userid);
DLLEXPORT(struct XfFriend*) XfireInst_FindUserBySid(XFINST inst, non0string *sid);
DLLEXPORT(struct XfFriend*) XfireInst_FindUserByUsername(XFINST inst, non0string *username);
DLLEXPORT(struct XfChatRoom*) XfireInst_FindCreateChatRoom(XFINST inst, non0string *gcid);
DLLEXPORT(struct XfChatRoom*) XfireInst_FindChatRoom(XFINST inst, non0string *gcid);
DLLEXPORT(struct XfChatRoom*) XfireInst_FindChatRoomByName(XFINST inst, non0string *name);
DLLEXPORT(struct XfChatRoomUser*) XfireInst_FindChatRoomUserByXfFriend(XFINST inst, struct XfChatRoom *xfgc, struct XfFriend *xff);
DLLEXPORT(struct XfClanEvent*) XfireInst_FindClanEventByEventid(XFINST inst, struct XfClan *xfc, unsigned int eventid);

DLLEXPORT(char*) XfireUtil_AvatarURL(struct XfFriend *user);
DLLEXPORT(unsigned char*) XfireUtil_GetNickname(struct XfFriend *user);
DLLEXPORT(int) XfireUtil_IsUserOnline(struct XfFriend *user);
DLLEXPORT(unsigned char *) XfireUtil_IPchar(unsigned int ip, unsigned char *ipchar);
DLLEXPORT(unsigned int) XfireUtil_IPvalue(unsigned char *ipchar);

DLLEXPORT(struct XfFriend*) XfireFriend(void);
DLLEXPORT(struct XfFavoriteServers*) XfireFavoriteServers(void);
DLLEXPORT(struct XfGameData*) XfireGameData(
	unsigned int gameid, unsigned int gameip, unsigned int gameport);
DLLEXPORT(struct XfGameDataExt*) XfireGameDataExt(void);
DLLEXPORT(struct XfFriendExt*) XfireFriendExtData(void);
DLLEXPORT(struct XfBroadcast*) XfireBroadcast(void);
DLLEXPORT(struct XfFriendP2P*) XfireFriendP2Pinfo(void);
DLLEXPORT(struct XfFriendsGroup*) XfireFriendsGroup(void);
DLLEXPORT(struct XfChatRoom*) XfireChatRoom(void);
DLLEXPORT(struct XfChatRoomUser*) XfireChatRoomUser(struct XfFriend *user, unsigned int permission);
DLLEXPORT(struct XfChatRoomVoice*) XfireChatRoomVoice(void);
DLLEXPORT(struct XfVoiceHostUser*) XfireVoiceHostUser(void);
DLLEXPORT(struct XfClan*) XfireClan(unsigned int clanid);
DLLEXPORT(struct XfScreenshotInfo*) XfireScreenshotInfo(void);
DLLEXPORT(struct XfVideoInfo*) XfireVideoInfo(void);
DLLEXPORT(struct XfClanMember*) XfireClanMember(struct XfFriend *user, non0string *nick, struct XfClan *xfc);
DLLEXPORT(struct XfClanNews*) XfireClanNews(unsigned int newsid);
DLLEXPORT(struct XfClanEvent*) XfireClanEvent(unsigned int eventid);
DLLEXPORT(struct XfGameServerList*) XfireGameServerList(unsigned int gameid, LinkedList *servers);

struct XfNetworkHandlerList *XfireNetworkHandlerList(unsigned int pid);
struct XfNetworkInstance *XfireNetworkInstance(int socketid);
int XfireInst_ProcessSendAction(struct XfNetworkInstance *xfn,
	unsigned int completed);

DLLEXPORT(void) FreeXfireInstance(XFINST obj);
DLLEXPORT(void) FreeXfireFriend(struct XfFriend *obj);
DLLEXPORT(void) FreeXfireFavoriteServers(struct XfFavoriteServers *obj);
DLLEXPORT(void) FreeXfireGameData(struct XfGameData *obj);
DLLEXPORT(void) FreeXfireGameDataExt(struct XfGameDataExt *obj);
DLLEXPORT(void) FreeXfireFriendExtData(struct XfFriendExt *obj);
DLLEXPORT(void) FreeXfireBroadcast(struct XfBroadcast *obj);
DLLEXPORT(void) FreeXfireFriendP2Pinfo(struct XfFriendP2P *obj);
DLLEXPORT(void) FreeXfireFriendsGroup(struct XfFriendsGroup *obj);
DLLEXPORT(void) FreeXfireFriendsGroupFull(struct XfFriendsGroup *obj);
DLLEXPORT(void) FreeXfireChatRoom(struct XfChatRoom *obj);
DLLEXPORT(void) FreeXfireChatRoomUser(struct XfChatRoomUser *obj);
DLLEXPORT(void) FreeXfireChatRoomUserFull(struct XfChatRoomUser *obj);
DLLEXPORT(void) FreeXfireChatRoomVoice(struct XfChatRoomVoice *obj);
DLLEXPORT(void) FreeXfireVoiceHostUser(struct XfVoiceHostUser *obj);
DLLEXPORT(void) FreeXfireClan(struct XfClan *obj);
DLLEXPORT(void) FreeXfireScreenshotInfo(struct XfScreenshotInfo *obj);
DLLEXPORT(void) FreeXfireVideoInfo(struct XfVideoInfo *obj);
DLLEXPORT(void) FreeXfireClanMember(struct XfClanMember *obj);
DLLEXPORT(void) FreeXfireClanNews(struct XfClanNews *obj);
DLLEXPORT(void) FreeXfireClanEvent(struct XfClanEvent *obj);
DLLEXPORT(void) FreeXfireGameServerList(struct XfGameServerList *obj);

void FreeXfireNetworkHandlerList(struct XfNetworkHandlerList *obj);
void FreeXfireNetworkInstance(struct XfNetworkInstance *obj);

int XfireAnalyze_FriendCMPFUNC(struct XfFriend *a, struct XfFriend *b);
int XfireAnalyze_FriendSidCMPFUNC(struct XfFriend *a, struct XfFriend *b);
int XfireAnalyze_GroupCMPFUNC(struct XfFriendsGroup *a,
	struct XfFriendsGroup *b);
int XfireAnalyze_ChatroomCMPFUNC(struct XfChatRoom *a, struct XfChatRoom *b);
int XfireAnalyze_ClanCMPFUNC(struct XfClan *a, struct XfClan *b);
int XfireAnalyze_ClanMemberCMPFUNC(struct XfClanMember *a, struct XfClanMember *b);
int XfireAnalyze_ChatMemberCMPFUNC(struct XfChatRoomUser *a, struct XfChatRoomUser *b);
int XfireAnalyze_ServerListCMPFUNC(struct XfGameServerList *a, struct XfGameServerList *b);
int XfireAnalyze_NetworkHandlerListCMPFUNC(
	struct XfNetworkHandlerList *a, struct XfNetworkHandlerList *b);

struct XfNetworkHandlerList *XfireAnalyze_FindNetworkHandlerList(
	BTree *tree, unsigned int pid);
int XfireAnalyze_CallRawHandlers (XFINST inst, non0string *data, struct XfirePacket *packet);
int XfireAnalyze_HandleInternally(XFINST inst, struct XfirePacket *packet);

#endif
